#include <iostream>
#include <memory>
#include <vector>
#include <string>
using namespace std;

class Test;
class Weak;
struct sInfo;

class Weak {
public:
    Weak() {
        m_text = "weak";
        cout << "new Weak:" << m_text << endl;
    }
    ~Weak() {
        cout << "delete Weak:" << m_text << endl;        
    }

    void show() {
        cout << m_text << endl;        
    }
protected:
    std::string m_text;
};

struct sInfo {
    std::string text;
    std::weak_ptr<Test> test;
    std::weak_ptr<Weak> weak;
    sInfo(std::weak_ptr<Test> _test, std::weak_ptr<Weak> _weak, std::string& _text) {
        test = _test;
        weak = _weak;
        text = _text;
        cout << "new sInfo: " << text << endl;
    }

    ~sInfo() {
        cout << "delete sInfo: " << text << endl;
    }
};

class Test : public std::enable_shared_from_this<Test> {
public:
    Test() {}
    ~Test() {}
    void add(std::weak_ptr<Weak> weak, int count) {
        for (int i = 0; i < count; ++i) {
            std::string text = "text" + std::to_string(i);
            std::shared_ptr<sInfo> info(new sInfo(shared_from_this(), weak, text));
            m_infos.push_back(info);
        }
    }
    void show() {
        cout << "---------------" << endl;
        for (auto it = m_infos.begin(); it != m_infos.end(); ++it) {
            cout << (*it)->text << endl;            
        }
        cout << "---------------" << endl;
    }

    void show(int idx) {
        auto info = m_infos.at(idx);
        cout << info->text << endl;
        if (!info->weak.expired()) {
            std::shared_ptr<Weak> weak = info->weak.lock();
            weak->show();
        }
        std::shared_ptr<Test> test = info->test.lock();
        if (test) {
            test->test();
        }
    }

    void clear() {
        m_infos.clear();
    }

    void test() {
        cout << "test:test" << endl;
    }
protected:
    std::vector<std::shared_ptr<sInfo>> m_infos;
};

int main(int argc, char** argv)
{
    cout << "hello world!" << endl;
    std::shared_ptr<Weak> weak(new Weak);
    std::shared_ptr<Test> test(new Test);
    test->add(weak, 5);
    test->show();
    test->show(2);
    test->show();
    weak = nullptr;
    test->show(2);
    test->show();
    test->clear();
    test->show();
    return 0;
}
